using UnityEngine;
using System.Collections;
using System.Collections.Generic;


public class LightRay : MonoBehaviour
{
	
	private Ray ray;
	private RaycastHit hit;

	public int maxReflexions = 20;
	public Color initColor = Color.white;
	public float thickness = 4.0f;
	public Material rayMat;
	public Material rayUndoMat;
	
	private VectorLine line;
	private List<Vector3> linePoints = new List<Vector3>();
	private List<Color> lineColors = new List<Color>();
	
	private LightHitInfo initHitInfo;
	private List<LightHitInfo> newRaysHitInfos = new List<LightHitInfo>();
	
	private int layermask;
	
	void Start ()
	{
		layermask = (1 << LayerMask.NameToLayer("GPObject")) | (1 << LayerMask.NameToLayer("Clickable"));
		
		LevelConstants.lineIndex++;

		linePoints.Add(transform.position);
		linePoints.Add(transform.right*20);
		
		lineColors.Add(initColor);
		line = new VectorLine("line"+LevelConstants.lineIndex, linePoints.ToArray(),lineColors.ToArray(), rayMat, thickness, LineType.Discrete);
		
	}

	void Update ()
	{
		if(THistory.Instance.isUndoing()){
			line.material = rayUndoMat;
		}else{
			line.material = rayMat;
		}
			
		initHitInfo = new LightHitInfo(transform.position,Vector3.zero,transform.right,initColor);
		
		linePoints.Clear();
		lineColors.Clear();
		
		traceNextRay(initHitInfo, null);
		
	}
	
	void traceNextRay(LightHitInfo hitInfo, GameObject lastHitted){
		
		linePoints.Add(hitInfo.Point);
		
		lineColors.Add(hitInfo.LightColor);
		
		if(Physics.Raycast(hitInfo.Point,hitInfo.Direction,out hit,20,layermask)){
			
			//Hack raycast same object
			if(lastHitted != null && lastHitted == hit.transform.gameObject){
				hitInfo.Point += Vector3.Scale(hitInfo.Direction,hit.transform.localScale/10);
				linePoints.RemoveAt(linePoints.Count-1);
				lineColors.RemoveAt(lineColors .Count-1);
				traceNextRay(hitInfo,lastHitted);
			}else{
				
				lastHitted = hit.collider.transform.gameObject;
				
				hitInfo = new LightHitInfo(hit.point,hit.normal,hitInfo.Direction,hitInfo.LightColor);
				
				if(hit.collider.transform.GetComponent<LightRayHandler>() == null){
					hitInfo.Direction = Vector3.zero;
					newRaysHitInfos = new List<LightHitInfo>(new LightHitInfo[]{hitInfo});
				}else{
					newRaysHitInfos = hit.transform.GetComponent<LightRayHandler>().getNextLightRay(hitInfo);
				}
				
				
				if(newRaysHitInfos[0].Direction != Vector3.zero){
					linePoints.Add(hitInfo.Point);
					
					if(linePoints.Count/2 <= maxReflexions){
						foreach(LightHitInfo newRayInfo in newRaysHitInfos){
							traceNextRay(newRayInfo, lastHitted);
						}
					}
					//sortie maxReflexions
				}else{
					linePoints.Add(hitInfo.Point);
					//sortie hit block
				}
				
				
			}
		}else{
			linePoints.Add(hitInfo.Point+(hitInfo.Direction*20));
			//sortie no hit
		}
	}
	
	void LateUpdate ()
	{
		
		line.Resize(linePoints.ToArray());
		line.SetColors(lineColors.ToArray());
		line.Draw3D();
	}
	
	public void initialize(Color c, float thickness = 4.0f){
		initColor = c;
		this.thickness = thickness;
	}
	
	void OnDestroy(){
		Destroy(line.vectorObject);	
	}
}